import fs from 'fs';
import url from 'url';
import path from 'path';
import yaml from 'yaml';

const __filename = url.fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const __dataDir = path.join(__dirname, '../data')


// 随机文件获取类
class RandomFilePicker {
    constructor() {
        // 缓存索引记录的文件目录
        this.dataDir = __dataDir;
        // 图库根路径
        this.imageDir = "/mnt/smb_share/";
        // 游戏名称与角色名称映射表
        this.gameCharacterMap = new Map();
        // 初始化文件信息
        this.#initDirFiles()
    }

    // 初始化文件信息
    #initDirFiles() {
        // 读取配置文件
        const configPath = path.join(__dirname, '../config/config.yaml');
        if (!fs.existsSync(configPath)) {
            console.error("配置文件不存在：", configPath);
            // 复制默认配置文件
            const defaultConfigPath = path.join(__dirname, '../config/config_default.yaml');
            fs.copyFileSync(defaultConfigPath, configPath);
            logger.info("配置文件不存在，已创建默认配置文件，请修改后重启。");
            return;
        }
        // 读取 YAML 文件内容
        const fileContent = fs.readFileSync(configPath, 'utf8');
        const config = yaml.parse(fileContent);
        this.imageDir = config.imageDir;
        // 相对路径转为绝对路径
        if (path.isAbsolute(this.imageDir) == false) {
            this.imageDir = path.resolve(__dirname, "..", this.imageDir);
        }
        // 检查图库路径是否存在
        if (fs.existsSync(this.imageDir) == false) {
            logger.error(logger.red(`图库路径不存在：${this.imageDir}，请检查配置文件`));
            return;
        }
        logger.info(logger.yellow("图库路径：", this.imageDir));

        // 读取根目录下的第一层级文件夹（游戏目录）
        const gameDirList = fs.readdirSync(this.imageDir);

        for (const gameName of gameDirList) {
            const gameDir = path.join(this.imageDir, gameName);
            // 过滤：仅处理目录（排除文件）
            const stats = fs.statSync(gameDir);
            if (!stats.isDirectory()) continue;

            // 读取当前第一层级文件夹下的第二层级文件夹（角色目录）
            const characterDirList = fs.readdirSync(gameDir);
            for (const characterName of characterDirList) {
                const characterDir = path.join(gameDir, characterName);
                // 过滤：仅处理目录（排除文件）
                const characterStats = fs.statSync(characterDir);
                if (!characterStats.isDirectory()) continue;
                // 建立游戏与角色的映射
                this.gameCharacterMap.set(characterName, gameName);
            }
        }
        logger.info(logger.yellow(`初始化图库角色映射共计 ${this.gameCharacterMap.size}个角色`));
    }

    // 根据计数倒序获取洗牌后的文件
    async getFile(characterName) {
        // 获取角色文件夹名称
        const gameName = this.gameCharacterMap.get(characterName);
        if (!gameName) {
            return null; // 如果没有找到对应的游戏目录，则返回 null
        }

        // 获取角色的文件列表
        let files = [];
        await global.redis.hGet("character-image", `files:${gameName}:${characterName}`).then((res) => {
            if (res !== null) {
                files = res.split(',');
            }
        });
        // 获取文件索引
        let index = 0;
        await global.redis.hGet("character-image", `index:${gameName}:${characterName}`).then((res) => {
            if (res !== null) {
                index = parseInt(res, 10);
            }
        });

        // 如果可用文件数为0，则对文件列表重新进行洗牌, 并缓存洗牌后的数据
        if (index == 0 || files.length === 0 || index > files.length) {
            logger.info(`角色 ${characterName} 的图片已全部使用完毕，重新洗牌。`);
            // 读取角色目录下的所有文件
            const characterDir = path.join(this.imageDir, gameName, characterName);
            files = fs.readdirSync(characterDir);
            // 重新洗牌并重置索引
            this.#shuffle(files);
            index = files.length - 1;
            // 缓存文件列表
            await global.redis.hSet("character-image", `files:${gameName}:${characterName}`, files.join(','));
        } else {
            // 文件计数减1
            index--;
        }
        // 刷新缓存索引
        await global.redis.hSet("character-image", `index:${gameName}:${characterName}`, index.toString());
        const imagePath = path.join(this.imageDir, gameName, characterName, files[index]);
        return imagePath;
    }

    // 统计所有角色的文件数量
    async countFiles() {
        const counts = [];
        for (const [characterName, gameName] of this.gameCharacterMap.entries()) {
            let index = 0;
            await global.redis.hGet("character-image", `index:${gameName}:${characterName}`).then((res) => {
                if (res !== null) {
                    index = parseInt(res, 10);
                }
            });

            let files = [];
            await global.redis.hGet("character-image", `files:${gameName}:${characterName}`).then((res) => {
                if (res !== null) {
                    files = res.split(',');
                }
            });
            counts.push({
                game: gameName,
                character: characterName,
                fileCount: files.length,
                index: index
            });
        }
        logger.info(`角色文件统计完成，共计${counts.length}个角色`);
        return counts;
    }

    // 洗牌算法
    #shuffle(array) {
        for (let i = array.length - 1; i > 0; i--) {
            // 在 [0, i] 范围内随机选择一个索引
            const j = Math.floor(Math.random() * (i + 1));
            // 交换元素
            [array[i], array[j]] = [array[j], array[i]];
        }
        return array;
    }
}

export default new RandomFilePicker();
